home *** CD-ROM | disk | FTP | other *** search
- /*
- * STevie - ST editor for VI enthusiasts. ...Tim Thompson...twitch!tjt...
- */
-
- #include <stdio.h>
- #include <ctype.h>
- #include "stevie.h"
-
- edit()
- {
- int c, c1, c2;
- char *p, *q;
-
- Prenum = 0;
-
- /* position the display and the cursor at the top of the file. */
- Topchar = Filemem;
- Curschar = Filemem;
- Cursrow = Curscol = 0;
-
- for ( ;; ) {
- /* Figure out where the cursor is based on Curschar. */
- cursupdate();
- if ( State == INSERT )
- message("Insert Mode");
- /* printf("Curschar=(%d,%d) row/col=(%d,%d)",
- Curschar,*Curschar,Cursrow,Curscol); */
- windgoto(Cursrow,Curscol);
- windrefresh();
- c = vgetc();
- if ( State != INSERT )
- message("");
- switch(State) {
- case NORMAL:
- /* We're in the normal (non-insert) mode. */
-
- /* Pick up any leading digits and compute 'Prenum' */
- if ( (Prenum>0 && isdigit(c)) || (isdigit(c) && c!='0') ){
- Prenum = Prenum*10 + (c-'0');
- break;
- }
- /* execute the command */
- normal(c);
- Prenum = 0;
- break;
- case INSERT:
- /* We're in insert mode. */
- switch(c){
- case '\033': /* an ESCape ends input mode */
-
- /* If we're past the end of the file, (which should */
- /* only happen when we're editing a new file or a */
- /* file that doesn't have a newline at the end of */
- /* the line), add a newline automatically. */
- if ( Curschar >= Fileend ) {
- insertchar('\n');
- Curschar--;
- }
-
- /* Don't end up on a '\n' if you can help it. */
- if ( Curschar>Filemem && *Curschar=='\n'
- && *(Curschar-1)!='\n' ) {
- Curschar--;
- }
- State = NORMAL;
- message("");
- Uncurschar = Insstart;
- Undelchars = Ninsert;
- /* Undobuff[0] = '\0'; */
- /* construct the Redo buffer */
- p=Redobuff;
- q=Insbuff;
- while ( q<Insptr )
- *p++ = *q++;
- *p++ = '\033';
- *p = '\0';
- updatescreen();
- break;
- case '\b':
- if ( Curschar <= Insstart )
- beep();
- else {
- int wasnewline = 0;
- if ( *Curschar == '\n' )
- wasnewline=1;
- Curschar--;
- delchar();
- Insptr--;
- Ninsert--;
- if ( wasnewline )
- Curschar++;
- cursupdate();
- updatescreen();
- }
- break;
- case '\030': /* control-x */
- { int wasnewline = 0; char *p1;
- p1 = Curschar;
- if ( *Curschar == '\n' )
- wasnewline = 1;
- inschar('[');
- inschar('x');
- cursupdate();
- updatescreen();
- c1 = gethexchar();
- inschar(c1);
- cursupdate();
- updatescreen();
- c2 = gethexchar();
- Curschar = p1;
- delchar();
- delchar();
- delchar();
- c = 16*hextoint(c1)+hextoint(c2);
- if(Debug)printf("(c=%d)",c);
- if ( wasnewline )
- Curschar++;
- inschar(c);
- Ninsert++;
- *Insptr++ = c;
- updatescreen();
- break;
- }
- case '\017':
- break;
- case '\r':
- c = '\n';
- /* This is SUPPOSED to fall down into 'default' */
- default:
- insertchar(c);
- break;
- }
- break;
- }
- }
- }
-
- insertchar(c)
- int c;
- {
- char *p;
-
- if ( ! anyinput() ) {
- inschar(c);
- *Insptr++ = c;
- Ninsert++;
- }
- else {
- /* If there's any pending input, grab */
- /* it all at once. */
- p = Insptr;
- *Insptr++ = c;
- Ninsert++;
- while ( (c=vpeekc()) != '\033' ) {
- c = vgetc();
- *Insptr++ = c;
- Ninsert++;
- }
- *Insptr = '\0';
- insstr(p);
- }
- updatescreen();
- }
-
- gethexchar()
- {
- int c;
-
- for ( ;; ) {
- windgoto(Cursrow,Curscol);
- windrefresh();
- c = vgetc();
- if ( hextoint(c) >= 0 )
- break;
- message("Expecting a hexidecimal character (0-9 or a-f)");
- beep();
- sleep(1);
- }
- return(c);
- }
-
- getout()
- {
- windgoto(Rows-1,0);
- windrefresh();
- putchar('\r');
- putchar('\n');
- windexit(0);
- }
-
- cursupdate()
- {
- char *p;
- int inc, c, nlines;
-
- /* special case: file is completely empty */
- if ( Fileend == Filemem ) {
- Topchar = Curschar = Filemem;
- }
- else if ( Curschar < Topchar ) {
- nlines = cntlines(Curschar,Topchar);
- /* if the cursor is above the top of */
- /* the screen, put it at the top of the screen.. */
- Topchar = Curschar;
- /* ... and, if we weren't very close to begin with, */
- /* we scroll so that the line is close to the middle. */
- if ( nlines > Rows/3 )
- scrolldown(Rows/3);
- else {
- /* make sure we have the current line completely */
- /* on the screen, by setting Topchar to the */
- /* beginning of the current line (in a strange way). */
- if ( (p=prevline(Topchar))!=NULL &&
- (p=nextline(p))!=NULL ) {
- Topchar = p;
- }
- }
- updatescreen();
- }
- else if ( Curschar >= Botchar && Curschar < Fileend ) {
- nlines = cntlines(Botchar,Curschar);
- /* If the cursor is off the bottom of the screen, */
- /* put it at the top of the screen.. */
- Topchar = Curschar;
- /* ... and back up */
- if ( nlines > Rows/3 )
- scrolldown((2*Rows)/3);
- else
- scrolldown(Rows-2);
- updatescreen();
- }
-
- Cursrow = Curscol = Cursvcol = 0;
- for ( p=Topchar; p<Curschar; p++ ) {
- c = *p;
- if ( c == '\n' ) {
- Cursrow++;
- Curscol = Cursvcol = 0;
- continue;
- }
- /* A tab gets expanded, depending on the current column */
- if ( c == '\t' )
- inc = (8 - (Curscol)%8);
- else
- inc = chars[(unsigned)(c & 0xff)].ch_size;
- Curscol += inc;
- Cursvcol += inc;
- if ( Curscol >= Columns ) {
- Curscol -= Columns;
- Cursrow++;
- }
- }
- }
-
- scrolldown(nlines)
- int nlines;
- {
- int n;
- char *p;
-
- /* Scroll up 'nlines' lines. */
- for ( n=nlines; n>0; n-- ) {
- if ( (p=prevline(Topchar)) == NULL )
- break;
- Topchar = p;
- }
- }
-
- /*
- * oneright
- * oneleft
- * onedown
- * oneup
- *
- * Move one char {right,left,down,up}. Return 1 when
- * sucessful, 0 when we hit a boundary (of a line, or the file).
- */
-
- oneright()
- {
- char *p;
-
- p = Curschar;
- if ( (*p++)=='\n' || p>=Fileend || *p == '\n' )
- return(0);
- Curschar++;
- return(1);
- }
-
- oneleft()
- {
- char *p;
-
- p = Curschar;
- if ( *p=='\n' || p==Filemem || *(p-1) == '\n' )
- return(0);
- Curschar--;
- return(1);
- }
-
- beginline()
- {
- while ( oneleft() )
- ;
- }
-
- oneup(n)
- {
- char *p, *np;
- int savevcol, k;
-
- savevcol = Cursvcol;
- p = Curschar;
- for ( k=0; k<n; k++ ) {
- /* Look for the previous line */
- if ( (np=prevline(p)) == NULL ) {
- /* If we've at least backed up a little .. */
- if ( k > 0 )
- break; /* to update the cursor, etc. */
- else
- return(0);
- }
- p = np;
- }
- Curschar = p;
- /* This makes sure Topchar gets updated so the complete line */
- /* is one the screen. */
- cursupdate();
- /* try to advance to the same (virtual) column */
- /* that we were at before. */
- Curschar = coladvance(p,savevcol);
- return(1);
- }
-
- onedown(n)
- {
- char *p, *np;
- int k;
-
- p = Curschar;
- for ( k=0; k<n; k++ ) {
- /* Look for the next line */
- if ( (np=nextline(p)) == NULL ) {
- if ( k > 0 )
- break;
- else
- return(0);
- }
- p = np;
- }
- /* try to advance to the same (virtual) column */
- /* that we were at before. */
- Curschar = coladvance(p,Cursvcol);
- return(1);
- }
-